package jmind.asteroidea.plugin.spring;

import jmind.asteroidea.annotations.Asteroidea;
import jmind.asteroidea.annotations.EnableAsteroidea;
import jmind.asteroidea.core.ClassFileScanner;
import jmind.asteroidea.registry.StarfishRegistry;
import jmind.base.util.reflect.ClassUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

import java.lang.reflect.Modifier;
import java.util.Set;

/**
 * description:
 *   BeanDefinitionRegistryPostProcessor
 * @author weibo.xie
 * @date:2022/7/7 上午11:23
 */
@Configuration
@Slf4j
public class AsteroideaBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {


    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableAsteroidea.class.getName()));
        String[] basePackages = annoAttrs.getStringArray("basePackages");
        Enum<?> proxyEnum = annoAttrs.getEnum("proxy");
        // 没有写明扫描包，默认加载main方法所在包。如果不是spring boot启动方式没有main方法抛异常
        if (basePackages.length == 0) {
            Class mainClass = ClassUtil.deduceMainClass();
            if (mainClass == null) {
                throw new RuntimeException("没有需要扫描的包， @EnableAsteroidea请配置basePackages需要扫描的包路径");
            }
            basePackages = new String[]{mainClass.getPackage().getName()};
        }
        for (String packagePath : basePackages) {
            ClassFileScanner scanner = new ClassFileScanner(packagePath);

            Set<Class> typesAnnotatedWith = scanner.getTypesAnnotatedWith(Asteroidea.class);

            for (Class superClass : typesAnnotatedWith) {
//                if (!superClass.isInterface()) {
//                    continue;
//                }
                //  这里支持接口和抽象类，但是@interface 注解类型返回也是true，所以要排除掉 9729
                //  接口：1537 ，抽象类：1025 注解：9729
                int mod=superClass.getModifiers();
                if(!Modifier.isAbstract(mod) || mod==9729){
                    continue;
                }

                RootBeanDefinition beanDefinition = new RootBeanDefinition();
                beanDefinition.setBeanClass(AsteroideaInterfaceProxyFactoryBean.class);
                beanDefinition.getPropertyValues().addPropertyValue("asteroideaInterfaceClass", superClass);
                beanDefinition.getPropertyValues().addPropertyValue("proxyEnum", proxyEnum);
                String beanName = superClass.getName();
                // 这里很关键，默认获取这个bean
                beanDefinition.setPrimary(true);
                beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
                // 获取子类
                Set<Class> subtypes = scanner.getSubTypesOf(superClass);
                //  注册所有实现类
                StarfishRegistry.getInstance().register(superClass,subtypes);

            }
        }
    }


}
